#include <stdio.h>
#include "app/app_message.h"
#include "thirdparty/log.h"
#include "thirdparty/cJSON.h"
#include <string.h>
#include <stdlib.h>



char * ByreEncryptString(void *ptr,int len);
int  StringAnalysistByte(char * ptr,char **str,int *len);


/**
 * brief 把一个josn格式转换成message格式
 *
 * param 
 * param 
 * return  成功返回0  失败返回-1
 */
int app_message_JosnTrunMessage(Message *message,char *json,int len)
{
     cJSON * root = NULL;
    //解析 josn字符串
    root =  cJSON_ParseWithLength(json,len);
    //判断是否解析成功
    if(root ==NULL)
    {
        log_warn("app_message_josnTrunMessage analysis josn fail");
        //失败
        return -1;
    }
    //根基字段获取数据
    cJSON *idItem = NULL;
    cJSON *magItem = NULL;
    cJSON *connectTypeItem = NULL;
    connectTypeItem = cJSON_GetObjectItem(root,"connectType");
    idItem = cJSON_GetObjectItem(root,"id");
    magItem = cJSON_GetObjectItem(root,"mag");
    //判断字段是否存在
    if(idItem == NULL || magItem == NULL || connectTypeItem == NULL)
    {
        //失败  数据有问题
        log_warn("app_message_josnTrunMessage analysis josn fail");
        cJSON_Delete(root);
        return -1;
    }
    //把数据通特殊方法解密  每俩个字节  解密成 一个字节 
    char * id_byte = NULL;
    char * mag_byte = NULL;
    StringAnalysistByte(idItem->valuestring,&id_byte,&message->id_len);
    StringAnalysistByte(magItem->valuestring,&mag_byte,&message->mag_len);

    //判断是否成功
    if(id_byte == NULL || mag_byte == NULL)
    {
        //没有分配空间说明失败了 解密失败
        log_warn("app_message_josnTrunMessage decode id or mag fail");
        cJSON_Delete(root);
        return -1;
    }

    //给ptr分配内存
    message->ptr = malloc(message->id_len + message->mag_len);

    message->connect_type = connectTypeItem->valuedouble; //类型
    memcpy(message->ptr,id_byte,message->id_len);         //ptr
    memcpy(message->ptr + message->id_len,mag_byte,message->mag_len);

    //释放内存
    free(id_byte);
    free(mag_byte);
    cJSON_Delete(root);
    return 0;
}

/**
 * brief 把一个message格式转换成json
 *
 * param len 需要转换的长度
 * param 
 * return 成功返回0  失败返回-1
 */

int app_message_MessageTrunJosn(Message *message,void *ptr,int len)
{
    //message   connectType = 1 id_len = 1 id_mag = 2 ptr = 0X0A0B0C(16镜子)
    //json格式  {"connectType": 1 , "id" : "0A"，”mag“ : "0B0C"}；  
    //把一个0x0a 这种16进子的数 变成 =字符从 ”0A“ 

    //创建一个cjson对象
    cJSON *obj = cJSON_CreateObject();
    //把数据冲一个字节的 变成2个字节的字符串
    char * string_id = NULL;
    string_id = ByreEncryptString(message->ptr,message->id_len);
    if(string_id == NULL)
    {
        log_error("app_message_MessageTrunJosn id enrypt fail");
        goto MEM_MALLOC_ID_FAIL;
    }
    char * string_mag = NULL;
    string_mag = ByreEncryptString(message->ptr + message->id_len , message->mag_len);
    if(string_mag == NULL)
    {
        log_error("app_message_MessageTrunJosn mag enrypt fail");
        goto MEM_MALLOC_MAG_FAIL;
    }

    //添加整数字段
    cJSON_AddNumberToObject(obj,"connectType",message->connect_type);
    //添加字符串字段
    cJSON_AddStringToObject(obj,"id",string_id);
    cJSON_AddStringToObject(obj,"mag",string_mag);

    //将Json转换成字符格式
    char * json =  cJSON_PrintUnformatted(obj);
    //判断长度是否正确
    if((int)strlen(json) + 1 > len)
    {
        //说明需要转换的长度不够
        goto LENGTH_NOT_FAIL;
    }
    //把数据拷贝到ptr
    strcpy(ptr,json);
    //释放内存
    //释放开辟的内存
    free(string_id);
    free(string_mag);
    free(json);
    cJSON_Delete(obj);

    return 0;

LENGTH_NOT_FAIL:
    free(string_mag);
    free(json);
MEM_MALLOC_MAG_FAIL:
    free(string_id);
MEM_MALLOC_ID_FAIL:
    cJSON_Delete(obj);
    return -1;
}


/// @brief 把一个message  转化成  bin格式
/// @param message 
/// @param bin 
/// @param len 
/// @return  成功返回lem  失败返回-1
int app_message_MessageTrunByte(Message *message,void * bin,int len)
{
    //判读长度是否正确
    if(message->id_len + message->mag_len + 3 > len)
    {
        //长度不够
        log_warn("app_message_MessageTrunByte length not enouge");
        return -1;
    }
    memcpy(bin,&message->connect_type,1);  //类型
    memcpy(bin+1,&message->id_len,1);      //id长度
    memcpy(bin+2,&message->mag_len,1);     //实际数据长度
    memcpy(bin+3,message->ptr,message->id_len + message->mag_len);  //实际数据加id
    log_trace("bin = %s",bin);
    return message->id_len + message->mag_len + 3;
}


/// @brief 把一个 byte转换成message
/// @param message 
/// @param bin 
/// @param len 
/// @return  成功返回长度  失败返 -1
int app_message_ByteTrunMessage(Message *message,void * bin,int len)
{
    //判断转化的长度是否正确
    if(len < 3)
    {
        //错误
        return -1;
    }
    //清空message
    memset(message,0,sizeof(Message));
    //拷贝数据
    memcpy(&message->connect_type,bin,1); //类型
    memcpy(&message->id_len,bin+1,1);     //id长度
    memcpy(&message->mag_len,bin+2,1);    //mag长度
    //分配内存
    message->ptr =  malloc(message->id_len + message->mag_len);
    //判断是否分配成功
    if(message == NULL)
    {
        //失败
        log_warn("app_message_ByteTrunMessage mempry alloc fail");
        return -1;
    }
    memcpy(message->ptr,bin+3,message->id_len+message->mag_len);
    log_trace("byte trun message succeed");
    return 0;
}


/// @brief 清除message内存
/// @param message 
void app_message_free(Message * message)
{
    //释放内存
    free(message->ptr);
}


/// @brief 把一个字节的数据加密成俩个字节
/// @param ptr
/// @param len 
/// @return 成功返回加密后的数据指针  失败返回null
char * ByreEncryptString(void *ptr,int len)
{
    //映射
    char ascell[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    char *str = malloc(len * 2 +1); //加1  是存放 /0的
    //判断是否开批成功
    if(str == NULL)
    {
        return NULL;
    }
    //加密数据
    unsigned char * array = ptr;
    for(int i = 0 ; i < len;i++)
    {
        str[i * 2] = ascell[(array[i] & 0xF0) >> 4];
        str[i * 2 +1] = ascell[(array[i] & 0X0F)];
    }
    //加上 /0
    str[len * 2] = '\0';
    return str;
}


/// @brief 把一个通过ByreEncryptString函数加密过的数据解密
/// @param ptr 
/// @param len 
/// @return 成功返回 0 失败返回 -1
int  StringAnalysistByte(char * ptr,char **str,int *len)
{
    int ptr_len = strlen(ptr);
    //首先判断数据长度是否正确 数据长度肯定三2的倍数
    if(ptr_len % 2 != 0)
    {
        //失败
        log_error("app_message StringAnalysistByte length eerro");
        return -1;
    }
    //给最后解密后的长度复制
    *len = ptr_len / 2;
    //分配内存
    *str = malloc(*len);
    //判断是否分配成功
    if(*str == NULL)
    {
        log_error("app_message StringAnalysistByte mem malloc  erreo");
        return -1;
    }
    //解密
    for(int i = 0 ; i < ptr_len ; i += 2)
    {
        unsigned char number = 0;
        //判断是0-9  还是A - F
        if(ptr[i] >= '0' && ptr[i] <= '9')
        {
            //0-9
            number += ptr[i] - '0';
        }
        else
        {
            //A - F
            number +=  ptr[i] - 'A' + 10;
        }

        //number << 4
        number <<= 4;

        if(ptr[i+1] >= '0' && ptr[i+1] <= '9')
        {
            //0-9
            number +=  ptr[i + 1] - '0';
        }
        else
        {
            //A - F
            number +=  ptr[i +1] - 'A' + 10;
        }
        //拷贝到str
        memcpy(*str + (i / 2),&number,1);
    }
    return 0;
}

